package com.embedsky.administrator.mycardreader;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.pm.PackageManager;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.embedsky.administrator.mycardreader.message.MessageAdapter;
import com.embedsky.administrator.mycardreader.message.SocketMessage;
import com.embedsky.administrator.mycardreader.p2p.DirectActionListen;
import com.embedsky.administrator.mycardreader.p2p.P2pManager;
import com.embedsky.administrator.mycardreader.p2p.WifiP2pBroadcastReceive;
import com.embedsky.administrator.mycardreader.p2p.WifiP2pConnectListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class MainActivity extends AppCompatActivity implements LoyaltyCardReader.AccountCallback {

    public static final String TAG = "MyCardReader";
    // Recommend NfcAdapter flags for reading from other Android devices. Indicates that this
    // activity is interested in NFC-A devices (including other Android devices), and that the
    // system should not check for the presence of NDEF-formatted data (e.g. Android Beam).
    public static int READER_FLAGS =
            NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK;
    public LoyaltyCardReader mLoyaltyCardReader;
    private TextView mAccountField;
    public static StringBuilder sb = new StringBuilder();

    private MainViewModel mainViewModel;

    private MessageAdapter messageAdapter;

    private RecyclerView recyclerView;

    private final String[] permissionList = {Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.CHANGE_NETWORK_STATE,
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.CHANGE_WIFI_STATE,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION};
    private String bleMac = "";
    private boolean connectEnable = false;

    private WifiP2pManager wifiP2pManager;
    private WifiP2pManager.Channel channel;
    private WifiP2pServiceInfo p2pServiceInfo;
    private BroadcastReceiver broadcastReceiver;
    private WifiP2pDeviceList deviceList;
    private WifiP2pInfo mWifiP2pInfo;
    private String ip;
    private boolean wifiP2pEnable = false;
    private boolean isConnected = false;
    private Handler handler;
    private EditText editText;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAccountField = (TextView) findViewById(R.id.data_tv);
        mLoyaltyCardReader = new LoyaltyCardReader(this);
        requestPermission();
        if (!allPermissionGrant()) {
            showToast("没有权限");
            return;
        }
        initDevice();
        enableReaderMode();
        initView();
        findViewById(R.id.discover_device).setOnClickListener((view) -> discoverPeers());
        findViewById(R.id.connect_device).setOnClickListener(v -> {
            if (connectEnable && !TextUtils.isEmpty(bleMac)) {
                connectTarget(bleMac);
            } else {
                showToast("连接条件不满足");
            }
        });
        findViewById(R.id.disconnect_device).setOnClickListener(v -> {
            disConnect();
        });
        findViewById(R.id.create_socket).setOnClickListener(v -> {
            Log.d(TAG, "onCreate: " + ip);
            //connectSocket();
        });

        findViewById(R.id.send_to_server).setOnClickListener(v -> {
            //mClientManager.sendData("hello server");
        });
    }


    @Override
    public void onPause() {
        super.onPause();
        disableReaderMode();
        unregisterReceiver(broadcastReceiver);
    }

    @Override
    public void onResume() {
        super.onResume();
        enableReaderMode();
        registerReceiver(broadcastReceiver, WifiP2pBroadcastReceive.getIntentFilter());
    }

    private void enableReaderMode() {
        Log.i(TAG, "Enabling reader mode");
        Activity activity = this;
        NfcAdapter nfc = NfcAdapter.getDefaultAdapter(activity);
        if (nfc != null) {
            nfc.enableReaderMode(activity, mLoyaltyCardReader, READER_FLAGS, null);
        }
    }

    private void initViewModel() {
        mainViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MainViewModel.class);
        mainViewModel.messageList.observe(this, (messageList) -> {
            Log.d(TAG, "initViewModel: " + messageList.toString());
            //D/MyCardReader: initViewModel: [SocketMessage{data='hello', type=0}]
            //messageAdapter.notify();
            msgList.add(messageList.get(messageList.size() - 1));
            messageAdapter.notifyItemInserted(messageList.size() - 1);
            recyclerView.scrollToPosition(messageList.size() - 1);
        });
    }

    List<SocketMessage> msgList = new ArrayList<>();

    private void initView() {
        recyclerView = findViewById(R.id.message_list);
        initViewModel();
        messageAdapter = new MessageAdapter(msgList);
        recyclerView.setAdapter(messageAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        editText = findViewById(R.id.msgText);
        findViewById(R.id.sendMsg).setOnClickListener(v -> {
            String text = editText.getText().toString();
            editText.setText("");
            if (!TextUtils.isEmpty(text)) {
                mainViewModel.sendData(text);
            }
        });
    }

    private void disableReaderMode() {
        Log.i(TAG, "Disabling reader mode");
        NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
        if (nfc != null) {
            nfc.disableReaderMode(this);
        }
    }

    @Override
    public void onAccountReceived(String bleMacAddress) {
        // This callback is run on a background thread, but updates to UI elements must be performed
        // on the UI thread.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mAccountField.setText(bleMacAddress);
                discoverPeers();
                showToast("读卡成功");
            }
        });
        connectEnable = true;
        bleMac = bleMacAddress;
    }

    private void requestPermission() {
        ActivityCompat.requestPermissions(this, permissionList, 1);
    }

    private boolean allPermissionGrant() {
        for (String permission : permissionList) {
            return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
        }
        return false;
    }

    private void initDevice() {
        wifiP2pManager = (WifiP2pManager) getSystemService(WIFI_P2P_SERVICE);
        if (wifiP2pManager == null) {
            finish();
            return;
        }
        channel = wifiP2pManager.initialize(this, getMainLooper(), directActionListen);
        broadcastReceiver = new WifiP2pBroadcastReceive(wifiP2pManager, channel, directActionListen);
        //registerReceiver(broadcastReceiver, WifiP2pBroadcastReceive.getIntentFilter());
    }


    @SuppressLint("MissingPermission")
    private void discoverPeers() {
        if (!wifiP2pEnable) {
            return;
        }
        //Toast.makeText(this, "正在搜索设备", Toast.LENGTH_SHORT).show();
        P2pManager.getInstance().discoverPeers(wifiP2pManager, channel);
    }

    private WifiP2pConnectListener wifiP2pConnectListener = new WifiP2pConnectListener() {
        @Override
        public void success() {
            //connectSocket();
        }

        @Override
        public void fail() {
            Log.d(TAG, "connect fail: ");
        }
    };

    @SuppressLint("MissingPermission")
    private void connectTarget(String bleMac) {
        WifiP2pConfig config = new WifiP2pConfig();
        config.deviceAddress = bleMac;
        config.wps.setup = WpsInfo.PBC;
        Log.d(TAG, "connectTarget: ");
        P2pManager.getInstance().connect(wifiP2pManager, config, channel);
    }

    private void disConnect() {
        P2pManager.getInstance().disconnect(wifiP2pManager, channel);
        P2pManager.getInstance().removeGroup(wifiP2pManager, channel);
        mainViewModel.stopClient();
        connectEnable = false;
        isConnected = false;
    }

    private void showToast(String hint) {
        Toast.makeText(this, hint, Toast.LENGTH_SHORT).show();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        disConnect();
    }

    private void getDeviceStatus(WifiP2pDevice device) {
        int status = device.status;
        switch (status) {
            case WifiP2pDevice.CONNECTED:
                Log.d(TAG, "getDeviceStatus: Connected");
            case WifiP2pDevice.AVAILABLE:
                Log.d(TAG, "getDeviceStatus: AVAILABLE");
            case WifiP2pDevice.FAILED:
                Log.d(TAG, "getDeviceStatus: FAILED");
            case WifiP2pDevice.INVITED:
                Log.d(TAG, "getDeviceStatus: INVITED");
            case WifiP2pDevice.UNAVAILABLE:
                Log.d(TAG, "getDeviceStatus: UNAVAILABLE");
        }
    }

    private DirectActionListen directActionListen = new DirectActionListen() {
        @Override
        public void onChannelDisconnected() {
            Log.d(TAG, "onChannelDisconnected: ");
            //connectEnable = false;
        }

        @Override
        public void wifiP2pEnabled(Boolean enabled) {
            wifiP2pEnable = enabled;
            Log.d(TAG, "wifiP2pEnabled: " + enabled);
        }

        @Override
        public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) {
            Log.d(TAG, "onConnectionInfoAvailable: " + "---isOwner==" + wifiP2pInfo.isGroupOwner + "---isFormed==" + wifiP2pInfo.groupFormed);
            if (!wifiP2pInfo.isGroupOwner && wifiP2pInfo.groupFormed) {
                mWifiP2pInfo = wifiP2pInfo;
                if (!TextUtils.isEmpty(mWifiP2pInfo.groupOwnerAddress.getHostAddress())) {
                    ip = mWifiP2pInfo.groupOwnerAddress.getHostAddress();
                    isConnected = true;
                    //connectSocket(messageListener);
                    mainViewModel.connectSocket(ip);
                } else {
                    showToast("IP为空");
                }
            }
        }

        @Override
        public void onDisconnection() {
            Log.d(TAG, "onDisconnection: ");
            //connectEnable = false;
        }

        @Override
        public void onSelfDeviceAvailable(WifiP2pDevice wifiP2pDevice) {
            Log.d(TAG, "onSelfDeviceAvailable: " + wifiP2pDevice);
        }

        @Override
        public void onPeersAvailable(Collection<WifiP2pDevice> wifiP2pDeviceList) {
            for (WifiP2pDevice device : wifiP2pDeviceList) {
                Log.d(TAG, "onPeersAvailable: " + device);
                Log.d(TAG, "onPeersAvailable: " + bleMac+"ddfdggg"+connectEnable+"ffdsfsd"+isConnected);
                if (Objects.equals(device.deviceAddress, bleMac) && connectEnable && !isConnected) {
                    Log.d(TAG, "connect to server: ");
                    connectTarget(bleMac);
                }
            }

        }

        @Override
        public void onGetDeviceInfo(WifiP2pDevice info) {

        }
    };
}